import urllib.parse
import datetime
import calendar
import requests
import json


def blockchair_time_to_utc_timestamp(time_str):
  timestamp_int = (
    calendar.timegm(
        datetime.datetime.strptime(time_str, '%Y-%m-%d %H:%M:%S').timetuple()
    ) * 10 ** 9
  )
  return int(timestamp_int)


class BtcNativePrivateClient:
  def __init__(self,
               *,
               host,
               api_key=None,
               timeout=60):
    self._host = host
    self._api_key = api_key
    self._timeout = timeout
    self._path_prefix = urllib.parse.urljoin(self._host, 'bitcoin/')

  def _get(self, path, params=None):
    url = urllib.parse.urljoin(self._path_prefix, path)
    params = params or {}
    if self._api_key:
      params['key'] = self._api_key
    response = requests.request('GET',
                                url,
                                params=params,
                                timeout=self._timeout)
    response.raise_for_status()
    content = response.json()
    return content

  def query_stats(self):
    return self._get('stats')

  def get_block_timestamp(self, block_number):
    response = self._get(f'dashboards/block/{block_number}')
    response = blockchair_time_to_utc_timestamp(
      response['data'][str(block_number)]['block']['time'])
    return response

  def get_latest_block_number_timestamp(self):
    stats = self.query_stats()
    block_num = stats['data']['best_block_height']
    block_time = blockchair_time_to_utc_timestamp(
      stats['data']['best_block_time'])
    return block_num, block_time

  def get_token_balance(
      self,
      address,
      end_height=None,
      transaction_limit=10,
      transaction_offset=0
  ):
    params = {
      'limit': f'{transaction_limit}',
      'offset': f'{transaction_offset}',
      'state': 'latest',
      'transaction_details': 'true',
    }
    response = self._get(
      f'dashboards/address/{address}', params=params)
    if response is None:
      balance = 0
    else:
      balance = response['data'][address]['address']['balance']
      txs = response['data'][address]['transactions']
      if end_height is not None:
        for tx in txs:
          tx_height = tx['block_id']
          if tx_height > end_height:
            balance_change = int(tx['balance_change'])
            balance -= balance_change
          if tx_height <= end_height:
            break
    return balance
